import struct
import socket

# Define the IP header structure
IP_HEADER_FORMAT = "!BBHHHBBH4s4s"

# Define the IP header fields
version = 4  # IPv4
ihl = 5  # Internet Header Length (in 32-bit words)
tos = 0  # Type of Service
total_len = 28  # Total length of the IP packet (header + data)
id = 54321  # Identification
flags = 0  # Flags (not fragmented)
frag_offset = 0  # Fragment offset
ttl = 64  # Time to Live
protocol = socket.IPPROTO_TCP  # Protocol (TCP in this example)
checksum = 0  # Checksum (calculated later)
src_ip = socket.inet_aton("192.168.1.100")  # Source IP address
dst_ip = socket.inet_aton("10.0.0.1")  # Destination IP address

# Create the IP header
ip_header = struct.pack(IP_HEADER_FORMAT,
                        (version << 4) + ihl,  # Version and IHL
                        tos,
                        total_len,
                        id,
                        (flags << 13) + frag_offset,  # Flags and Fragment Offset
                        ttl,
                        protocol,
                        checksum,
                        src_ip,
                        dst_ip)

# Calculate the IP header checksum
checksum = calculate_checksum(ip_header)
ip_header = struct.pack(IP_HEADER_FORMAT,
                        (version << 4) + ihl,
                        tos,
                        total_len,
                        id,
                        (flags << 13) + frag_offset,
                        ttl,
                        protocol,
                        checksum,
                        src_ip,
                        dst_ip)

# Define the payload (data)
payload = b"Hello, World!"

# Combine the IP header and payload to form the IP packet
ip_packet = ip_header + payload

# Function to calculate the IP header checksum
def calculate_checksum(data):
    checksum = 0
    for i in range(0, len(data), 2):
        word = (data[i] << 8) + (data[i + 1])
        checksum += word
    while checksum >> 16:
        checksum = (checksum & 0xFFFF) + (checksum >> 16)
    checksum = ~checksum & 0xFFFF
    return checksum

